﻿using HashTag;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Microsoft.Practices.EnterpriseLibrary.Logging
{
    /// <summary>
    /// Contains extensions for EntLib to expose message builder and other helpful add-ins.
    /// </summary>
    public static class EntLibExtensions
    {
        /// <summary>
        /// Create a 'Critical' level message automatically capturing HttpContext, UserContext, and MachineContext
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="ex">Exception, if provided, to associated with this message</param>
        /// <returns>Builder suitable for capturing log message properties</returns>
        public static LogMessageBuilder Critical(this LogWriter writer, Exception ex=null)
        {
            return makeBuilder(writer, TraceEventType.Critical,ex).HttpContext().MachineContext().UserContext();
        }

        /// <summary>
        /// Create a 'Error' level message automatically capturing HttpContext, UserContext, and MachineContext
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="ex">Exception, if provided, to associated with this message</param>
        /// <returns>Builder suitable for capturing log message properties</returns>
        public static LogMessageBuilder Error(this LogWriter writer, Exception ex = null)
        {
            return makeBuilder(writer, TraceEventType.Error, ex).HttpContext().MachineContext().UserContext();
        }

        /// <summary>
        /// Create a 'Warning' level message automatically capturing HttpContext, UserContext, and MachineContext
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="ex">Exception, if provided, to associated with this message</param>
        /// <returns>Builder suitable for capturing log message properties</returns>
        public static LogMessageBuilder Warning(this LogWriter writer, Exception ex = null)
        {
            return makeBuilder(writer, TraceEventType.Warning, ex).HttpContext().MachineContext().UserContext();
        }

        /// <summary>
        /// Create an 'Information' level message
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="ex">Exception, if provided, to associated with this message</param>
        /// <returns>Builder suitable for capturing log message properties</returns>
        public static  LogMessageBuilder Info(this LogWriter writer)
        {
            return makeBuilder(writer, TraceEventType.Information);
        }

        /// <summary>
        /// Create an 'Information' level message
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="ex">Exception, if provided, to associated with this message</param>
        /// <returns>Builder suitable for capturing log message properties</returns>
        public static LogMessageBuilder Verbose(this LogWriter writer)
        {
            return makeBuilder(writer, TraceEventType.Verbose);
        }
    
        /// <summary>
        /// Add an error message to <paramref name="le"/> and expand exception details into <paramref name="le"/>.ExtendedProperties.  NOTE:  Use this method 
        /// when using native EntLob logging api.  Use Capture(ex) when using Fluent API or dupicate data may result
        /// </summary>
        /// <param name="le"></param>
        /// <param name="ex"></param>
        /// <returns></returns>
        public static LogEntry AddError(this LogEntry le, Exception ex)
        {

            le.AddErrorMessage(ex.Message);
            
            int lastException=1;
            var key = string.Format("Exception[{0}]", lastException);
            while (le.ExtendedProperties.ContainsKey(key) == false)
            {
                lastException++;
                key = string.Format("Exception[{0}]", lastException);
            }
            le.ExtendedProperties[key] = new LogException(ex);
            return le;
        }

        /// <summary>
        /// Add key-value pair to the exceptions ex.Data collection
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="key"></param>
        /// <param name="data"></param>
        /// <returns>Reference to <paramref name="ex"/></returns>
        public static Exception AddData(this Exception ex, string key, object data)
        {
            ex.Data[key] = data;
            return ex;
        }

        private static LogMessageBuilder makeBuilder(LogWriter writer, TraceEventType eventType, Exception ex = null)
        {
            var lmb = new LogMessageBuilder();
            lmb.Writer = writer;

            if (ex != null)
            {
                lmb.Catch(ex);
            }

            lmb.EventType(eventType);
            return lmb;
        }

    }
}
